package ru.vsu.amm.main;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Scanner;

import ru.vsu.amm.calculus.Cholesky;
import ru.vsu.amm.calculus.GeneralizedSystem;
import ru.vsu.amm.calculus.ThreeTwoDimensionalMatrix;
import ru.vsu.amm.input.Input;
import ru.vsu.amm.scenes.DemoLauncher;
import ru.vsu.amm.scenes.bulk.HedgehodDemo;

public class Main {
	
	private static long start;
	
	public static void main(String[] args) throws Exception {
		Input in = getNewInput();
		if (in == null || !in.isValid()) {
			System.out.println("Ошибка входных данных");
			return;
		}
		
		start();
		
		ThreeTwoDimensionalMatrix tm = ThreeTwoDimensionalMatrix.calculate(in.Nx, in.Ny, in.Nz);
		System.out.println("Ширина ленты: " + tm.getL());
		
		GeneralizedSystem gs = GeneralizedSystem.formGeneralizedSystem(in.E, in.nu, in.hx, in.hy, in.hz,
			tm.getMDisplacment(), tm.getTableAdjacency(), in.boundaryConditions, tm.getL());
		
		Cholesky ch = Cholesky.process(gs.getBand(), gs.getF());
		
		double calcTimeSeconds = finish();
		System.out.println(String.format("Время вычислений : %s секунд", calcTimeSeconds));
		
		// ru.vsu.amm.calculus.test.TestUtils.printToFile(gs, "generalized-system.txt");
		System.out.println("Мера точности метода Холецкого: " + ch.getPrecision());
		
		double[][] data = makeData(ch.getSolution());
		saveDataToFile(data); // solution is represented by matrix, and it will be in data.txt file
		
		HedgehodDemo demo = new HedgehodDemo(in.Nx, in.Ny, in.Nz, (float) in.hx, (float) in.hy, (float) in.hz);
		demo.setData(data);
		DemoLauncher.openDemo(demo);
	}
	
	public static Input getNewInput() {
		Input in = null;
		try (Scanner sc = new Scanner(System.in)) {
			System.out.print("Введите номер тестового файла: ");
			int number = sc.nextInt();
			
			in = new Input(number);
		} catch (Exception e) {
			System.out.println("Непредвиденная ошибка: " + e.getMessage());
		}
		
		return in;
	}
	
	private static double[][] makeData(double[] array){
		int N = array.length / 3;
		double[][] matrix = new double[N][3];
		int k = 0;
		for (int i = 0; i < N; i++)
			for (int j = 0; j < 3; j++)
				matrix[i][j] = array[k++];
		
		return matrix;
	}
	
	private static void saveDataToFile(double[][] matrix){
		try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("Data.txt"), "UTF-8"))) {
			for (int i=0; i<matrix.length; i++){
				bw.write(String.format("%-10d %-15e %-15e %-15e", i, matrix[i][0], matrix[i][1], matrix[i][2]));
				bw.newLine();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private static void start() {
		start = System.nanoTime();
	}
	
	private static double finish() {
		long finish = System.nanoTime();
		
		return (finish - start) / 1E+9;
	}
}